<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><script>(()=>{const r=navigator.serviceWorker,e=()=>console.error("Service Worker 注册失败！可能是由于您的浏览器不支持该功能！");r?.register("/sw.js")?.catch(e)||e()})()</script><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>gulp 详解与使用 | Alcex</title><noscript>开启JavaScript才能访问本站哦~</noscript><link rel="icon" href="/img/pwa/favicon.ico"><link rel="stylesheet" href="/css/index.css?v=1.9.2"><link rel="stylesheet" href="https://cdn2.codesign.qq.com/icons/7pOrz0WXB5ZWJPX/latest/iconfont.css"><link rel="stylesheet" href="https://cdn.staticfile.net/aplayer/1.10.1/APlayer.min.css"><link rel="stylesheet" href="https://cdn.staticfile.net/Swiper/11.0.5/swiper-bundle.min.css"><link rel="stylesheet" href="https://cdn.staticfile.net/fancyapps-ui/5.0.36/fancybox/fancybox.min.css"><meta name="description" content="什么是 gulpgulp 是一个前端构建工具，它能通过自动执行常见任务，比如编译预处理 CSS ，压缩 JavaScript 和刷新浏览器，来改进网站开发的过程，从而使开发更加快速高效。 为什么要用 gulp与 grunt 相比，gulp 无需写一大堆繁杂的配置参数，API（中文 API） 也非常简"><meta name="theme-color" content="#006a73"><meta name="apple-mobile-web-app-status-bar-style" content="#006a73"><link rel="manifest" href="/manifest.json"><meta name="msapplication-TileColor" content="#006a73"><link rel="mask-icon" href="/img/pwa/favicon.ico" color="#006a73"><link rel="apple-touch-icon" sizes="180x180" href="/img/pwa/favicon.ico"><link rel="icon" type="image/png" sizes="16x16" href="/img/pwa/favicon_16.ico"><link rel="icon" type="image/png" sizes="32x32" href="/img/pwa/favicon_32.ico"><link rel="bookmark" href="/img/pwa/favicon.ico"><script>console.log("%c Program: Hexo %c Theme: Solitude %c Version: v1.9.2","border-radius:5px 0 0 5px;padding: 5px 10px;color:white;background:#ff3842;","padding: 5px 10px;color:white;background:#3e9f50;","padding: 5px 10px;color:white;background:#0084ff;")</script><link rel="stylesheet" href="https://cdn.cbd.int/lxgw-wenkai-screen-webfont@1.7.0/style.css" media="print" onload='this.media="all"'><link rel="stylesheet" href="/static/css/custom.css"><script>(()=>{const e={set:function(e,t,n){if(0===n)return;const o=864e5*n,a={value:t,expiry:(new Date).getTime()+o};localStorage.setItem(e,JSON.stringify(a))},get:function(e){const t=localStorage.getItem(e);if(!t)return;const n=JSON.parse(t);if(!((new Date).getTime()>n.expiry))return n.value;localStorage.removeItem(e)}};window.utils={saveToLocal:e,getCSS:(e,t=!1)=>new Promise(((n,o)=>{const a=document.createElement("link");a.rel="stylesheet",a.href=e,t&&(a.id=t),a.onerror=o,a.onload=a.onreadystatechange=function(){const e=this.readyState;e&&"loaded"!==e&&"complete"!==e||(a.onload=a.onreadystatechange=null,n())},document.head.appendChild(a)})),getScript:(e,t={})=>new Promise(((n,o)=>{const a=document.createElement("script");a.src=e,a.async=!0,a.onerror=o,a.onload=a.onreadystatechange=function(){const e=this.readyState;e&&"loaded"!==e&&"complete"!==e||(a.onload=a.onreadystatechange=null,n())},Object.keys(t).forEach((e=>{a.setAttribute(e,t[e])})),document.head.appendChild(a)})),addGlobalFn:(e,t,n=!1,o=window)=>{const a=o.globalFn||{},r=a[e]||{};n&&r[n]||(r[n=n||Object.keys(r).length]=t,a[e]=r,o.globalFn=a)}}})()</script><script>const GLOBAL_CONFIG={root:"/",algolia:{appId:"D5AFXJ4K4D",apiKey:"343fe8f1a83d5d4a330df6d7923ebe25",indexName:"blog",hits:{per_page:10}},localsearch:void 0,runtime:"2023-01-11 00:00:00",lazyload:{enable:!0,error:"/img/error_load.png"},copyright:!1,highlight:{enable:!0,limit:200,expand:!0,copy:!0,syntax:"highlight.js"},randomlink:!0,lang:{theme:{dark:"已切换至深色模式",light:"已切换至浅色模式"},copy:{success:"复制成功",error:"复制失败"},backtop:"返回顶部",time:{day:"天前",hour:"小时前",just:"刚刚",min:"分钟前",month:"个月前"},f12:"开发者模式已打开，请遵循GPL协议。",totalk:"无需删除空行，直接输入评论即可",search:{empty:"找不到你查询的内容：${query}",hit:"找到 ${hits} 条结果，用时 ${time} 毫秒",placeholder:"输入关键词快速查找",count:"共 <b>${count}</b> 条结果。"},barrage:{title:"热评"}},aside:{sayhello:{morning:"一日之计在于晨",noon:"吃饱了才有力气干活",afternoon:"集中精力，攻克难关",night:"不要太劳累了，早睡更健康",goodnight:"睡个好觉，保证精力充沛"},sayhello2:["🤖️ 数码科技爱好者","🔍 分享与热心帮助","🔨 设计开发一条龙","🤝 专修交互与设计","🧱 团队小组发动机","🎮 电竞游戏爱好者"]},covercolor:{enable:!0},comment:{avatar:"https://cravatar.cn",commentBarrage:!0},lightbox:"fancybox",post_ai:{key:"9naCaYfLKM6fPL66XuRR",talk:"我是Alcex的摘要生成助理TianliGPT，TianliGPT在静态部署时进行摘要的撰写。我在这里只负责已经生成的摘要显示，你无法与我直接沟通，但我可以回答一些预设的问题。",randomPost:!0},right_menu:{mode:{dark:"深色模式",light:"浅色模式"},img_error:"此图片无法复制与下载",music:{start:"播放音乐",stop:"暂停音乐"},barrage:{open:"显示热评",close:"关闭热评"},translate:{translateDelay:0,defaultEncoding:2}}}</script><script id="config-diff">var PAGE_CONFIG={is_post:!0,is_page:!1,is_home:!1,page:"",toc:!0,comment:!0,ai_text:!1}</script><script defer src="/sw-dom.js"></script><meta name="generator" content="Hexo 7.1.1"><link rel="alternate" href="/atom.xml" title="Alcex" type="application/atom+xml"></head><body id="body"><canvas id="universe"></canvas><div id="console"><div class="close-btn" onclick="sco.hideConsole()"><i class="solitude st-close-fill"></i></div><div class="console-card-group"><div class="console-card-group-left"><div class="console-card" id="card-newest-comments" onclick="sco.hideConsole()"><div class="card-content"><div class="author-content-item-tips">互动</div><div class="author-content-item-title">最新评论</div></div><div class="aside-list"></div></div></div><div class="console-card-group-right"><div class="console-card tags" onclick="sco.hideConsole()"><div class="card-content"><div class="author-content-item-tips">标签</div><div class="author-content-item-title">寻找感兴趣的领域</div></div><div class="card-tag-cloud"><a href="/tags/%E7%99%BD%E5%AB%96/">白嫖<sup>1</sup></a><a href="/tags/gulp/">gulp<sup>1</sup></a><a href="/tags/hexo/">hexo<sup>1</sup></a><a href="/tags/ipv6/">ipv6<sup>1</sup></a><a href="/tags/vercel/">vercel<sup>1</sup></a><a href="/tags/cloudflare/">cloudflare<sup>1</sup></a><a href="/tags/Github-Action/">Github Action<sup>1</sup></a></div></div><div class="console-card history" onclick="sco.hideConsole()"><ul class="card-archive-list"><li class="card-archive-list-item"><a class="card-archive-list-link" onclick='pjax.loadUrl("/archives/2024/05/")' href="javascript:void(0);"><span class="card-archive-list-date">2024/05</span><div class="card-archive-list-count-group"><span class="card-archive-list-count">2</span><span class="card-archive-list-count-unit">篇</span></div></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" onclick='pjax.loadUrl("/archives/2023/04/")' href="javascript:void(0);"><span class="card-archive-list-date">2023/04</span><div class="card-archive-list-count-group"><span class="card-archive-list-count">1</span><span class="card-archive-list-count-unit">篇</span></div></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" onclick='pjax.loadUrl("/archives/2022/05/")' href="javascript:void(0);"><span class="card-archive-list-date">2022/05</span><div class="card-archive-list-count-group"><span class="card-archive-list-count">1</span><span class="card-archive-list-count-unit">篇</span></div></a></li></ul></div></div></div><div class="button-group"><div class="console-btn-item"><span class="darkmode_switchbutton" onclick="sco.switchDarkMode()" title="昼夜切换"><i class="solitude st-moon-clear-fill"></i></span></div><div class="console-btn-item" id="consoleHideAside"><span class="asideSwitch" onclick="sco.switchHideAside()" title="边栏显示控制"><i class="solitude st-side-bar-fill"></i></span></div><div class="console-btn-item" id="consoleKeyboard" onclick="sco.switchKeyboard()"><span class="keyboardSwitch" title="键盘快捷键"><i class="solitude st-keyboard-box-fill"></i></span></div><div class="console-btn-item" id="consoleMusic" onclick="sco.musicToggle()"><span class="music-switch" title="音乐开关"><i class="solitude st-disc-fill"></i></span></div><div class="console-btn-item on" id="consoleCommentBarrage" onclick="sco.switchCommentBarrage()"><span class="commentBarrage"><i class="solitude st-chat-fill"></i></span></div></div><div class="console-mask" onclick="sco.hideConsole()"></div></div><div id="sidebar" style="zoom:1"><div id="menu-mask" style="display:none"></div><div id="sidebar-menus"><div class="site-data"><div class="data-item is-center"><div class="data-item-link"><a href="/archives/"><div class="headline">文章</div><div class="length-num">4</div></a></div></div><div class="data-item is-center"><div class="data-item-link"><a href="/categories/"><div class="headline">分类</div><div class="length-num">4</div></a></div></div><div class="data-item is-center"><div class="data-item-link"><a href="/tags/"><div class="headline">标签</div><div class="length-num">7</div></a></div></div></div><span class="sidebar-menu-item-title">功能</span><div class="sidebar-menu-item"><span class="darkmode_switchbutton menu-child" onclick="sco.switchDarkMode()"><i class="solitude st-moon-clear-fill"></i><span>显示模式</span></span></div><div class="back-menu-list-groups"><div class="back-menu-list-group"><div class="back-menu-list-title">项目</div><div class="back-menu-list"><a class="back-menu-item" target="_blank" rel="noopener" href="https://status.alcex.cn" title="UptimeKuma"><img class="nolazyload back-menu-item-icon" src="/static/img/svg/uptimekuma.svg" alt="UptimeKuma"><span class="back-menu-item-text">UptimeKuma</span></a><a class="back-menu-item" target="_blank" rel="noopener" href="https://api.alcex.cn" title="像素云API"><img class="nolazyload back-menu-item-icon" src="/static/img/avatar.jpeg" alt="像素云API"><span class="back-menu-item-text">像素云API</span></a></div></div></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><span>首页</span></a></div><div class="menus_item"><a class="site-page" href="javascript:void(0);"><span>文库</span></a><ul class="menus_item_child"><li><a class="site-page child" href="/archives/"><i class="solitude st-folder-fill"></i><span>文章列表</span></a></li><li><a class="site-page child" href="/categories/"><i class="solitude st-checkbox-multiple-blank-fill"></i><span>全部分类</span></a></li><li><a class="site-page child" href="/tags/"><i class="solitude st-price-tag-fill"></i><span>全部标签</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="javascript:void(0);"><span>友链</span></a><ul class="menus_item_child"><li><a class="site-page child" href="/moments/"><i class="solitude st-wifi-fill"></i><span>友链鱼塘</span></a></li><li><a class="site-page child" href="/links/"><i class="solitude st-group-fill"></i><span>友情链接</span></a></li><li><a class="site-page child" href="javascript:travelling()"><i class="solitude st-gift-fill"></i><span>宝藏博主</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="javascript:void(0);"><span>我的</span></a><ul class="menus_item_child"><li><a class="site-page child" href="/gallery/"><i class="solitude st-image-fill"></i><span>相册集</span></a></li><li><a class="site-page child" href="/tlink/"><i class="solitude st-tools-fill"></i><span>工具箱</span></a></li><li><a class="site-page child" href="/music/"><i class="solitude st-disc-fill"></i><span>音乐馆</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="javascript:void(0);"><span>关于</span></a><ul class="menus_item_child"><li><a class="site-page child" href="/about/"><i class="solitude st-contacts-fill"></i><span>关于本站</span></a></li></ul></div></div><span class="sidebar-menu-item-title">标签</span><div class="card-widget card-tags card-archives card-webinfo card-allinfo"><div class="card-tag-cloud"><a href="/tags/%E7%99%BD%E5%AB%96/">白嫖<sup>1</sup></a><a href="/tags/gulp/">gulp<sup>1</sup></a><a href="/tags/hexo/">hexo<sup>1</sup></a><a href="/tags/ipv6/">ipv6<sup>1</sup></a><a href="/tags/vercel/">vercel<sup>1</sup></a><a href="/tags/cloudflare/">cloudflare<sup>1</sup></a><a href="/tags/Github-Action/">Github Action<sup>1</sup></a></div></div></div></div><div id="keyboard-tips"><div class="keyboardTitle">博客快捷键</div><div class="keyboardList"><div class="keyboardItem"><div class="keyGroup"><div class="key">Shift</div><div class="key">K</div></div><div class="keyContent"><div class="content">关闭快捷键功能</div></div></div><div class="keyboardItem"><div class="keyGroup"><div class="key">Shift</div><div class="key">A</div></div><div class="keyContent"><div class="content">打开中控台</div></div></div><div class="keyboardItem"><div class="keyGroup"><div class="key">Shift</div><div class="key">M</div></div><div class="keyContent"><div class="content">播放/暂停音乐</div></div></div><div class="keyboardItem"><div class="keyGroup"><div class="key">Shift</div><div class="key">L</div></div><div class="keyContent"><div class="content">打开友情链接</div></div></div></div></div><script>const keyboard_addKeyup=e=>{"Shift"===e.key&&document.getElementById("keyboard-tips").classList.remove("show")},keyboard_addKeydown=e=>{const o=[{name:"关闭快捷键功能",key:"K",func:"keyboard"},{name:"打开中控台",key:"A",sco:"showConsole"},{name:"播放/暂停音乐",key:"M",sco:"musicToggle"},{name:"打开友情链接",key:"L",url:"/links/"}];16===e.keyCode&&document.getElementById("keyboard-tips").classList.add("show");for(let d=0;d<o.length;d++)o[d].url?o[d].url.startsWith("http")?e.key===o[d].key&&window.open(o[d].url):e.key===o[d].key&&pjax.loadUrl(o[d].url):o[d].sco?e.key===o[d].key&&sco[o[d].sco]():o[d].func&&e.key===o[d].key&&window[o[d].func]()};function openKeyboard(){window.addEventListener("keyup",keyboard_addKeyup),window.addEventListener("keydown",keyboard_addKeydown)}function closeKeyboard(){window.removeEventListener("keyup",keyboard_addKeyup),window.removeEventListener("keydown",keyboard_addKeydown)}var sco_keyboards="true"===localStorage.getItem("keyboard");sco_keyboards&&(openKeyboard(),document.getElementById("consoleKeyboard").classList.add("on"))</script><div class="post" id="body-wrap"><header class="post-bg" id="page-header"><nav class="show" id="nav"><div id="nav-group"><div id="blog_name"><div class="back-home-button" tabindex="-1"><i class="back-home-button-icon solitude st-more-fill"></i><div class="back-menu-list-groups"><div class="back-menu-list-group"><div class="back-menu-list-title">项目</div><div class="back-menu-list"><a class="back-menu-item" target="_blank" rel="noopener" href="https://status.alcex.cn" title="UptimeKuma"><img class="nolazyload back-menu-item-icon" src="/static/img/svg/uptimekuma.svg" alt="UptimeKuma"><span class="back-menu-item-text">UptimeKuma</span></a><a class="back-menu-item" target="_blank" rel="noopener" href="https://api.alcex.cn" title="像素云API"><img class="nolazyload back-menu-item-icon" src="/static/img/avatar.jpeg" alt="像素云API"><span class="back-menu-item-text">像素云API</span></a></div></div></div></div><a id="site-name" href="/" title="返回博客主页"><span class="title">Alcex</span></a></div><div id="page-name-mask"><div id="page-name"><a id="page-name-text" onclick="sco.toTop()">gulp 详解与使用</a></div></div><div id="menus"><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><span>首页</span></a></div><div class="menus_item"><a class="site-page" href="javascript:void(0);"><span>文库</span></a><ul class="menus_item_child"><li><a class="site-page child" href="/archives/"><i class="solitude st-folder-fill"></i><span>文章列表</span></a></li><li><a class="site-page child" href="/categories/"><i class="solitude st-checkbox-multiple-blank-fill"></i><span>全部分类</span></a></li><li><a class="site-page child" href="/tags/"><i class="solitude st-price-tag-fill"></i><span>全部标签</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="javascript:void(0);"><span>友链</span></a><ul class="menus_item_child"><li><a class="site-page child" href="/moments/"><i class="solitude st-wifi-fill"></i><span>友链鱼塘</span></a></li><li><a class="site-page child" href="/links/"><i class="solitude st-group-fill"></i><span>友情链接</span></a></li><li><a class="site-page child" href="javascript:travelling()"><i class="solitude st-gift-fill"></i><span>宝藏博主</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="javascript:void(0);"><span>我的</span></a><ul class="menus_item_child"><li><a class="site-page child" href="/gallery/"><i class="solitude st-image-fill"></i><span>相册集</span></a></li><li><a class="site-page child" href="/tlink/"><i class="solitude st-tools-fill"></i><span>工具箱</span></a></li><li><a class="site-page child" href="/music/"><i class="solitude st-disc-fill"></i><span>音乐馆</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="javascript:void(0);"><span>关于</span></a><ul class="menus_item_child"><li><a class="site-page child" href="/about/"><i class="solitude st-contacts-fill"></i><span>关于本站</span></a></li></ul></div></div></div><div id="nav-left"></div><div id="nav-right"><div class="nav-button" id="travellings_button"><a class="site-page" target="_blank" rel="noopener" href="https://www.travellings.cn/go.html"><i class="solitude st-train-line"></i></a></div><div class="nav-button" id="refresh"><a class="site-page" href="/" onclick="refreshCache()"><i class="solitude i.fas.fa-refresh.fa-spin"></i></a></div><div class="nav-button" id="randomPost_button"><a class="site-page" onclick="toRandomPost()" title="随机一篇文章" href="javascript:void(0);"><i class="solitude st-signal-tower-fill"></i></a></div><div class="nav-button" id="search-button"><a class="site-page social-icon search" href="javascript:void(0);" title="搜索"><i class="solitude st-search-line"></i></a></div><div class="nav-button" id="nav-console"><a class="console_switchbutton" onclick="sco.showConsole()" title="中控台" href="javascript:void(0);"><i class="solitude st-dashboard-fill"></i></a></div><div class="nav-button" id="nav-totop" onclick="sco.toTop()"><a class="totopbtn"><i class="solitude st-arrow-up-line"></i><span id="percent">0</span></a></div><div id="toggle-menu"><a class="site-page"><i class="solitude st-menu-line"></i></a></div></div></div></nav><div class="coverdiv" id="coverdiv"><img class="nolazyload" id="post-cover" src="https://bu.dusays.com/2024/05/05/66365fd49d7f5.jpg" alt="gulp 详解与使用"></div><div id="post-info"><div id="post-firstinfo"><div class="meta-firstline"><a class="post-meta-original" title="该文章为原创文章，注意版权协议">原创</a><span class="post-meta-categories"><a class="post-meta-categories" href="/categories/%E5%89%8D%E7%AB%AF/">前端</a></span><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/gulp/"><span class="tags-name tags-punctuation">gulp</span></a></div></div></div></div><h1 class="post-title">gulp 详解与使用</h1><div id="post-meta"><div class="meta-secondline"><span class="post-meta-date" title="发布于 2024-05-01 17:25:24"><i class="post-meta-icon solitude st-calendar-todo-fill"></i><time datetime="2024-05-01T09:25:24.000Z">2024-05-01T09:25:24.000Z</time></span><span class="post-meta-date" title="最后更新于 2024-05-04 16:18:46"><i class="post-meta-icon solitude st-refresh-line"></i><time datetime="2024-05-04T08:18:46.860Z">2024-05-04T08:18:46.860Z</time></span><span class="post-meta-wordcount"><i class="post-meta-icon solitude st-word-fill" title="文章字数"></i><span class="word-count">4.3k</span><span class="post-meta-separator"></span><i class="post-meta-icon solitude st-clock-fill" title="阅读耗时"></i><span>17 min</span></span><span class="post-meta-position" title="作者IP归属地为周口"><i class="post-meta-icon solitude st-map-pin-fill"></i><span>周口</span></span><a class="post-meta-pv" href="/posts/486480be/" title="文章热度"><i class="post-meta-icon solitude st-fire-fill"></i><span id="twikoo_visitors"><i class="solitude st-loading-line"></i></span></a><span class="post-meta-commentcount" title="评论数" onclick='sco.scrollTo("post-comment")'><i class="solitude st-chat-fill"></i><a href="/posts/486480be/#post-comment"><span class="twikoo-count"><i class="solitude st-loading-line"></i></span></a></span></div></div></div><section class="main-hero-waves-area waves-area"><svg class="waves-svg" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" viewBox="0 24 150 28" preserveAspectRatio="none" shape-rendering="auto"><defs><path id="gentle-wave" d="M-160 44c30 0 58-18 88-18s58 18 88 18 58-18 88-18 58 18 88 18v44h-352Z"></path></defs><g class="parallax"><use href="#gentle-wave" x="48" y="0"></use><use href="#gentle-wave" x="48" y="3"></use><use href="#gentle-wave" x="48" y="5"></use><use href="#gentle-wave" x="48" y="7"></use></g></svg></section></header><main class="layout" id="content-inner"><div id="post"><div class="post-ai"><div class="ai-title"><div class="ai-title-left"><i class="ai-title-icon solitude st-robot-fill"></i><div class="ai-title-text">文章摘要</div></div><div class="ai-tag" id="ai-tag">GPT 4</div></div><div class="ai-explanation" style="display:block"></div><div class="ai-suggestions"></div><div class="ai-bottom"><div class="ai-tips">此内容根据文章生成，并经过人工审核，仅用于文章内容的解释与总结</div></div></div><article class="post-content" id="article-container"><h1 id="什么是-gulp"><a href="#什么是-gulp" class="headerlink" title="什么是 gulp"></a>什么是 gulp</h1><p><a target="_blank" rel="noopener" href="http://gulpjs.com/">gulp</a> 是一个前端构建工具，它能通过自动执行常见任务，比如编译预处理 CSS ，压缩 JavaScript 和刷新浏览器，来改进网站开发的过程，从而使开发更加快速高效。</p><h1 id="为什么要用-gulp"><a href="#为什么要用-gulp" class="headerlink" title="为什么要用 gulp"></a>为什么要用 gulp</h1><p>与 grunt 相比，gulp 无需写一大堆繁杂的配置参数，<a target="_blank" rel="noopener" href="https://github.com/gulpjs/gulp/blob/master/docs/API.md">API</a>（<a target="_blank" rel="noopener" href="http://www.gulpjs.com.cn/docs/api/">中文 API</a>） 也非常简单，学习起来很容易，而且 gulp 使用的是 nodejs 中 <a target="_blank" rel="noopener" href="https://nodejs.org/api/stream.html">stream</a> 来读取和操作数据，其速度更快。<br>gulp 有庞大的生态圈，且每天都在发展。依靠成千上万可供选择的插件，你可以利用 gulp 自动完成几乎任何事。</p><h1 id="如何使用-gulp"><a href="#如何使用-gulp" class="headerlink" title="如何使用 gulp"></a>如何使用 gulp</h1><h2 id="Installing-Gulp"><a href="#Installing-Gulp" class="headerlink" title="Installing Gulp"></a>Installing Gulp</h2><p>新版的 gulp 命令行工具已经改名为 gulp-cli 。<br>如果你之前安装了全局的 gulp 。在使用新的 gulp-cli 之前，执行命令<br><code>npm rm --global gulp</code> ，将之前的全局 gulp 卸掉。</p><span id="more"></span><h3 id="Install-the-gulp-command"><a href="#Install-the-gulp-command" class="headerlink" title="Install the gulp command"></a>Install the gulp command</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install --global gulp-cli</span><br></pre></td></tr></table></figure><h3 id="Install-gulp-in-your-devDependencies"><a href="#Install-gulp-in-your-devDependencies" class="headerlink" title="Install gulp in your devDependencies"></a>Install gulp in your devDependencies</h3><p>Run this command in your project directory</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install --save-dev gulp</span><br></pre></td></tr></table></figure><h2 id="Create-a-gulpfile"><a href="#Create-a-gulpfile" class="headerlink" title="Create a gulpfile"></a>Create a gulpfile</h2><p>Create a file called gulpfile.js in your project root with these contents:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> gulp = <span class="built_in">require</span>(<span class="string">&#x27;gulp&#x27;</span>);</span><br><span class="line"></span><br><span class="line">gulp.<span class="title function_">task</span>(<span class="string">&#x27;default&#x27;</span>, <span class="keyword">function</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="comment">// place code for your default tash here</span></span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><h2 id="Test-it-out"><a href="#Test-it-out" class="headerlink" title="Test it out"></a>Test it out</h2><p>Run the gulp command in your projct directory:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gulp</span><br></pre></td></tr></table></figure><h1 id="gulp-API"><a href="#gulp-API" class="headerlink" title="gulp API"></a>gulp API</h1><p>gulp 的核心 API 有四个：gulp.task() 、 gulp.src() 、 gulp.dest() 、 gulp.watch() 。<br><a target="_blank" rel="noopener" href="https://github.com/gulpjs/gulp/blob/master/docs/API.md">gulp API</a><br><a target="_blank" rel="noopener" href="http://www.gulpjs.com.cn/docs/api/">gulp API 中文</a></p><p>下面详细介绍一下：</p><h2 id="gulp-src"><a href="#gulp-src" class="headerlink" title="gulp.src()"></a>gulp.src()</h2><p>gulp.src() 可以读取你需要操作的文件，相比于 Grunt 主要以文件为媒介来运行它的工作流，gulp 使用的是 Nodejs 中的 <a target="_blank" rel="noopener" href="https://nodejs.org/api/stream.html">stream</a> 流，首先获取到需要的 stream ，然后可以通过 stream 的 pipe() 方法把流导入到你想要的地方，比如 gulp 的插件中，经过插件处理后的流又可以继续导入到其他插件中，当然也可以把流写入到文件中。所以 gulp 是以 stream 为媒介的，它不需要频繁的生成临时文件，这也是 gulp 的速度比 Grunt 快的一个原因。再回到正题上来，gulp.src() 方法正是用来获取流的，但要注意这个流里的内容不是原始的文件流，而是一个虚拟文件对象流（Vinyl files），这个虚拟文件对象中存储着原始文件的路径、文件名、内容等信息，这个我们暂时不用去深入理解，你只需简单的理解可以用这个方法来读取你需要操作的文件就行了。其语法为：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gulp.<span class="title function_">src</span>(globs [, options])</span><br></pre></td></tr></table></figure><p>gulp 用到的 glob 的匹配规则以及一些文件匹配技巧。<br>gulp 内部使用了 node-glob 模块来实现其文件匹配功能。我们可以使用下面这些特殊的字符来匹配我们想要的文件：</p><ul><li><code>*</code> 匹配文件路径中的 0 个或多个字符，但不会匹配路径分配符，除非路径分隔符出现在末尾</li><li>** 匹配路径中的 0 个或多个目录及其子目录，需要单独出现，即它左右不能有其他东西了。如果出现在末尾，也能匹配文件。</li><li>? 匹配文件路径中的一个字符（不会匹配路径分隔符）</li><li>[…] 匹配方括号中出现的字符中的任意一个，当方括号中第一个字符为 ^ 或 ! 时，则表示不匹配方括号中出现的其他字符中的任意一个，类似 js 正则表达式中的用法。</li><li>!(pattern|pattern|pattern) 匹配任何与括号中给定的任一模式都不匹配的</li><li>?(pattern|pattern|pattern) 匹配括号中给定的任一模式 0 次或 1 次，类似于 js 正则中的(pattern|pattern|pattern)?</li><li>+(pattern|pattern|pattern) 匹配括号中给定的任一模式至少 1 次，类似于正则中的(pattern|pattern|pattern)+</li><li><code>*(pattern|pattern|pattern)</code> 匹配括号中的给定的任一模式 0 次或多次，类似于 js 正则中的 <code>(pattern|pattern|pattern)*</code></li><li>@(pattern|pattern|pattern) 匹配括号中给定的任一模式 1 次，类似于 js 正则中的(pattern|pattern|pattern)</li></ul><p>下面以一系列例子来加深理解</p><ul><li><code>*</code> 能匹配 a.js 、 x.y 、 abc 、 abc&#x2F; ，但不能匹配 a&#x2F;b.js</li><li><code>*.*</code> 能匹配 a.js 、 style.css 、 a.b 、 x.y</li><li><code>*/*/*.js</code> 能匹配 a&#x2F;b&#x2F;c.js 、 x&#x2F;y&#x2F;z.js ，不能匹配 a&#x2F;b.js 、a&#x2F;b&#x2F;c&#x2F;d.js</li><li>** 能匹配 abc 、 a&#x2F;b.js 、 a&#x2F;b&#x2F;c.js 、 x&#x2F;y&#x2F;z 、x&#x2F;y&#x2F;z&#x2F;a.b ，能用来匹配所有的目录和文件</li><li>**&#x2F;*.js 能匹配 foo.js 、 a&#x2F;foo.js 、 a&#x2F;b&#x2F;foo.js 、 a&#x2F;b&#x2F;c&#x2F;foo.js</li><li>a&#x2F;**&#x2F;z 能匹配 a&#x2F;z 、 a&#x2F;b&#x2F;z 、 a&#x2F;b&#x2F;c&#x2F;z 、 a&#x2F;d&#x2F;g&#x2F;h&#x2F;r&#x2F;z</li><li><code>a/**b/z</code> 能匹配 a&#x2F;b&#x2F;z 、 a&#x2F;fb&#x2F;z ，但不能匹配 a&#x2F;x&#x2F;gb&#x2F;z ，因为只有单 ** 单独出现才能匹配多级目录</li><li>?.js 能匹配 a.js 、 b.js 、 c.js</li><li>a?? 能匹配 a.b 、 abc ，但不能匹配 ab&#x2F; ，因为它不会匹配路径分隔符</li><li>[xyz].js 只能匹配 x.js 、 y.js 、 z.js ，不会匹配 xy.js 、 xyz.js 等，整个中括号只代表一个字符</li><li>[^xyz].js 能匹配 a.js 、 b.js 、 c.js 等，不能匹配 x.js 、 y.js 、 z.js</li></ul><p>当有多种匹配模式时可以使用数组</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 使用数组的方式来匹配多种文件</span></span><br><span class="line">gulp.<span class="title function_">src</span>([<span class="string">&#x27;js/*.js&#x27;</span>,<span class="string">&#x27;css/*.css&#x27;</span>,<span class="string">&#x27;*.html&#x27;</span>])</span><br></pre></td></tr></table></figure><p>使用数组的方式还有一个好处就是可以很方便的使用排除模式，在数组中的单个匹配模式前加上 ! 即是排除模式，它会在匹配的结果中排除这个匹配，要注意一点的是不能在数组中的第一个元素中使用排除模式</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">gulp.<span class="title function_">src</span>([*.<span class="property">js</span>,<span class="string">&#x27;!b*.js&#x27;</span>])  <span class="comment">//匹配所有 js 文件，但排除掉以 b 开头的 js 文件</span></span><br><span class="line">gulp.<span class="title function_">src</span>([<span class="string">&#x27;!b*.js&#x27;</span>,*.<span class="property">js</span>])  <span class="comment">//不会排除任何文件，因为排除模式不能出现在数组的第一个元素中</span></span><br></pre></td></tr></table></figure><p>此外，还可以使用展开模式。展开模式以花括号作为定界符，根据它里面的内容，会展开为多个模式，最后匹配的结果为所有展开的模式想加起来得到的结果。展开的例子如下：</p><ul><li>a{b,c}d 会展开为 abd 、 acd</li><li>a{b,}c 会展开为 abc 、 ac</li><li>a{0..3}d 会展开为 a0d 、 a1d 、 a2d 、 a3d</li><li>a{b,c{d,e}f}g 会展开为 abg 、 acdfg 、 acefg</li><li>a{b,c}d{e,f}g 会展开为 abdeg 、 acdeg 、 abdfg 、 abdeg</li></ul><h2 id="gulp-dest"><a href="#gulp-dest" class="headerlink" title="gulp.dest()"></a>gulp.dest()</h2><p>gulp.dest() 方法是用来写文件的，其语法为：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gulp.<span class="title function_">dest</span>(path[, options])</span><br></pre></td></tr></table></figure><p><strong>path</strong> 为写入文件的路径<br>我们给 gulp.dest() 传入的路径参数，只能用来指定要生成的文件的目录，而不能指定生成文件的文件名，它生成文件的文件名使用的是导入到它的文件流自身的文件名，所以生成的文件名是由导入到它的文件流决定的，即使我们给它传入一个带有文件名的路径参数，然后它也会把这个文件名当作是目录名，例如：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> gulp = <span class="built_in">require</span>(<span class="string">&quot;gulp&quot;</span>);</span><br><span class="line">gulp.<span class="title function_">src</span>(<span class="string">&quot;script/jquery.js&quot;</span>).<span class="title function_">pipe</span>(gulp.<span class="title function_">dest</span>(<span class="string">&quot;dist/foo.js&quot;</span>));</span><br><span class="line"><span class="comment">// 最终生成的文件路径为 dist/foo.js/jquery.js ，而不是 dist/foo.js</span></span><br></pre></td></tr></table></figure><p>要想改变文件名，可以使用插件 gulp-rename<br>下面说说生成的文件路径与我们给 gulp.dest() 方法传入的路径参数之间的关系。<br>gulp.dest(path) 生成的文件路径是我们传入的 path 参数后面再加上 gulp.src() 中有通配符开始出现的那部分路径。例如：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> gulp = <span class="built_in">require</span>(<span class="string">&quot;gulp&quot;</span>);</span><br><span class="line"><span class="comment">//有通配符开始出现的那部分路径为 **/*.js</span></span><br><span class="line">gulp.<span class="title function_">src</span>(<span class="string">&quot;script/**/*.js&quot;</span>).<span class="title function_">pipe</span>(gulp.<span class="title function_">dest</span>(<span class="string">&quot;dist&quot;</span>));</span><br><span class="line"><span class="comment">//最后生成的文件路径为 dist/**/*.js</span></span><br><span class="line"><span class="comment">//如果 **/*.js 匹配到的文件为 jquery/jquery.js ，则生成的文件路径为 dist/jquery/jquery.js</span></span><br></pre></td></tr></table></figure><p>再举更多一点的例子</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">gulp.<span class="title function_">src</span>(<span class="string">&quot;script/avalon/avalon.js&quot;</span>).<span class="title function_">pipe</span>(gulp.<span class="title function_">dest</span>(<span class="string">&quot;dist&quot;</span>));</span><br><span class="line"><span class="comment">//没有通配符出现的情况，最后生成的文件路径为 dist/avalon.js</span></span><br><span class="line"></span><br><span class="line">gulp.<span class="title function_">src</span>(<span class="string">&quot;script/**/underscore.js&quot;</span>).<span class="title function_">pipe</span>(gulp.<span class="title function_">dest</span>(<span class="string">&quot;dist&quot;</span>));</span><br><span class="line"><span class="comment">//有通配符开始出现的那部分路径为 **/underscore.js</span></span><br><span class="line"><span class="comment">//假设匹配到的文件为script/util/underscore.js</span></span><br><span class="line"><span class="comment">//则最后生成的文件路径为dist/util/underscore.js</span></span><br><span class="line"></span><br><span class="line">gulp.<span class="title function_">src</span>(<span class="string">&quot;script/*&quot;</span>).<span class="title function_">pipe</span>(gulp.<span class="title function_">dest</span>(<span class="string">&quot;dist&quot;</span>));</span><br><span class="line"><span class="comment">//有通配符出现的那部分路径为*</span></span><br><span class="line"><span class="comment">//假设匹配到的文件为script/zepto.js</span></span><br><span class="line"><span class="comment">//则最后生成的文件路径为dist/zepto.js</span></span><br></pre></td></tr></table></figure><p>通过指定 gulp.src() 方法配置参数中的 base 属性，我们可以灵活的来改变 gulp.dest() 生成的文件路径。<br>当我们没有在 gulp.src() 方法配置参数中的 base 属性，base 的默认值为通配符开始出现之前那部分路径，例如：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gulp.<span class="title function_">src</span>(<span class="string">&quot;app/src/**/*.css&quot;</span>) <span class="comment">//此时base的值为 app/src</span></span><br></pre></td></tr></table></figure><p>上面我们说的 gulp.dest() 所生成的文件路径的规则，其实也可以理解成，用我们给 gulp.dest() 传入的路径替换掉 gulp.src() 中的 base 路径，最终得到生成文件的路径。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">gulp.<span class="title function_">src</span>(<span class="string">&quot;app/src/**/*.css&quot;</span>).<span class="title function_">pipe</span>(gulp.<span class="title function_">dest</span>(<span class="string">&quot;dist&quot;</span>));</span><br><span class="line"><span class="comment">//此时base的值为app/src，也就是说它的base路径为app/src</span></span><br><span class="line"><span class="comment">//设该模式匹配到了文件app/src/css/normal.css</span></span><br><span class="line"><span class="comment">//用dist替换掉base路径，最终得到dist/css/normal.css</span></span><br></pre></td></tr></table></figure><p>所以改变 base 路径后，gulp.dest() 生成的文件路径也会改变</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">gulp.<span class="title function_">src</span>(<span class="string">&quot;script/lib/*.js&quot;</span>).<span class="title function_">pipe</span>(gulp.<span class="title function_">dest</span>(<span class="string">&quot;build&quot;</span>));</span><br><span class="line"><span class="comment">//没有配置base参数，此时默认的base路径为script/lib</span></span><br><span class="line"><span class="comment">//假设匹配到的文件为script/lib/jquery.js</span></span><br><span class="line"><span class="comment">//生成的文件路径为build/jquery.js</span></span><br><span class="line"></span><br><span class="line">gulp.<span class="title function_">src</span>(<span class="string">&quot;script/lib/*.js&quot;</span>, &#123;<span class="attr">base</span>: <span class="string">&quot;script&quot;</span>&#125;).<span class="title function_">pipe</span>(gulp.<span class="title function_">dest</span>(<span class="string">&quot;build&quot;</span>));</span><br><span class="line"><span class="comment">//配置了base参数，此时base路径为script</span></span><br><span class="line"><span class="comment">//假设匹配到的文件为script/lib/jquery.js</span></span><br><span class="line"><span class="comment">//此时生成的文件路径为build/lib/jquery.js</span></span><br></pre></td></tr></table></figure><p>用 gulp.dest() 把文件流写入文件后，文件流仍然可以继续使用。</p><h2 id="gulp-task"><a href="#gulp-task" class="headerlink" title="gulp.task()"></a>gulp.task()</h2><p>gulp.task 方法用来定义任务，内部使用的是 Orchestrator ，其语法为：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gulp.<span class="title function_">task</span>(name[, deps], fn)</span><br></pre></td></tr></table></figure><p><strong>name</strong> 为任务名，如果你需要在命令行中运行你的某些任务，那么，请不要在名字中使用空格。<br><strong>deps</strong> 是当前定义的任务需要依赖的其他任务，为一个数组。当前定义的任务会在所有依赖的任务执行完毕后才开始执行。如果没有依赖，则可省略这个参数。<br><strong>fn</strong> 为任务函数，我们把任务要执行的代码都要写在里面。该参数也是可选的。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">gulp.<span class="title function_">task</span>(<span class="string">&quot;mytask&quot;</span>, [<span class="string">&quot;array&quot;</span>, <span class="string">&quot;of&quot;</span>, <span class="string">&quot;task&quot;</span>, <span class="string">&quot;names&quot;</span>], <span class="keyword">function</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="comment">//定义一个有依赖的任务</span></span><br><span class="line">  <span class="comment">// Do something</span></span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>关于 gulp.task() ，我们需要知道执行多个任务时怎么来控制任务执行的顺序。<br>gulp 中执行多个任务，可以通过任务依赖来实现。例如我想要执行 one ，two ，three 这三个任务，那我们就可以定义一个空的任务，然后把那三个任务当做这个空的任务的依赖就行了：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//只要执行default任务，就相当于把one,two,three这三个任务执行了</span></span><br><span class="line">gulp.<span class="title function_">task</span>(<span class="string">&#x27;default&#x27;</span>,[<span class="string">&#x27;one&#x27;</span>,<span class="string">&#x27;two&#x27;</span>,<span class="string">&#x27;three&#x27;</span>]);</span><br></pre></td></tr></table></figure><p>如果任务相互之间没有依赖，任务会按你书写的顺序来执行，如果有依赖的话则会先执行依赖的任务。<br>但是如果某个任务所依赖的任务是异步的，就要注意了，gulp 并不会等待那个所依赖的异步任务完成，而是会接着执行后续的任务。例如：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">gulp.<span class="title function_">task</span>(<span class="string">&#x27;one&#x27;</span>, <span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">  <span class="comment">// one是一个异步执行的任务</span></span><br><span class="line">  <span class="built_in">setTimeout</span>(<span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;one is done&quot;</span>);</span><br><span class="line">  &#125;,<span class="number">3000</span>);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">//two任务虽然依赖于one任务，但并不会等到one任务中的异步操作完成后再执行</span></span><br><span class="line">gulp.<span class="title function_">task</span>(<span class="string">&quot;two&quot;</span>, [<span class="string">&quot;one&quot;</span>], <span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;two is done&quot;</span>);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p><img src="/static/img/svg/loading.svg" data-lazy-src="https://i-s1.hydun.com/6/2024/05/02/663393a93fa9a.png"><br>上面的例子中我们执行 two 任务时，会先执行 one 任务，但不会去等待 one 任务中的异步操作完成后再执行 two 任务，而是紧接着执行 two 任务。因为 one 任务耗时 3 秒，所以 two 任务会在 one 任务中的异步操作完成之前就执行了。</p><p>那如果我们想等待异步任务中的异步操作完成后再执行后续的任务，该怎么做呢？<br>有三种方法可以实现：</p><p>第一：在异步操作完成后执行一个回调函数来通知 gulp 这个异步任务已经完成，这个回调函数就是任务函数的第一个参数。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">gulp.<span class="title function_">task</span>(<span class="string">&quot;one&quot;</span>, <span class="keyword">function</span>(<span class="params">cb</span>) &#123;</span><br><span class="line">  <span class="comment">//cb为任务函数提供的回调，用来通知任务已经完成</span></span><br><span class="line">  <span class="comment">//one是一个异步执行的任务</span></span><br><span class="line">  <span class="built_in">setTimeout</span>(<span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;one is done&quot;</span>);</span><br><span class="line">    <span class="title function_">cb</span>(); <span class="comment">//执行回调，表示这个异步任务已经完成</span></span><br><span class="line">  &#125;,<span class="number">5000</span>);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">//这时two任务会在one任务中的异步操作完成后再执行</span></span><br><span class="line">gulp.<span class="title function_">task</span>(<span class="string">&quot;two&quot;</span>, [<span class="string">&quot;one&quot;</span>], <span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;two is done&quot;</span>);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>第二：定义任务时返回一个流对象。适用于任务就是操作 gulp.src 获取到的流的情况。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">gulp.<span class="title function_">task</span>(<span class="string">&quot;one&quot;</span>, <span class="keyword">function</span>(<span class="params">cb</span>) &#123;</span><br><span class="line">  <span class="keyword">var</span> stream = gulp.<span class="title function_">src</span>(<span class="string">&quot;client/**/*.js&quot;</span>)</span><br><span class="line">      .<span class="title function_">pipe</span>(<span class="title function_">dosomething</span>()) <span class="comment">//dosomething()中有某些异步操作</span></span><br><span class="line">      .<span class="title function_">pipe</span>(gulp.<span class="title function_">dest</span>(<span class="string">&quot;build&quot;</span>));</span><br><span class="line">  <span class="keyword">return</span> stream;</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 这是two任务会在one任务中的异步操作完成后再执行</span></span><br><span class="line">gulp.<span class="title function_">task</span>(<span class="string">&quot;two&quot;</span>, [<span class="string">&quot;one&quot;</span>], <span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;two is done&quot;</span>);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>第三：返回一个 promise 对象，例如：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> Q = <span class="built_in">require</span>(<span class="string">&#x27;q&#x27;</span>); <span class="comment">//一个著名的异步处理的库 https://github.com/kriskowal/q</span></span><br><span class="line">gulp.<span class="title function_">task</span>(<span class="string">&quot;one&quot;</span>, <span class="keyword">function</span>(<span class="params">cb</span>)&#123;</span><br><span class="line">  <span class="keyword">var</span> deferred = Q.<span class="title function_">defer</span>();</span><br><span class="line">  <span class="comment">//做一些异步操作</span></span><br><span class="line">  <span class="built_in">setTimeout</span>(<span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">    deferred.<span class="title function_">resolve</span>();</span><br><span class="line">  &#125;,<span class="number">5000</span>);</span><br><span class="line">  <span class="keyword">return</span> deferred.<span class="property">promise</span>;</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">gulp.<span class="title function_">task</span>(<span class="string">&quot;two&quot;</span>, [<span class="string">&quot;one&quot;</span>], <span class="keyword">function</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;two is done&quot;</span>);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>关于 gulp.task() ，主要的就是要清除当依赖异步任务时要如何处理。</p><h2 id="gulp-watch"><a href="#gulp-watch" class="headerlink" title="gulp.watch()"></a>gulp.watch()</h2><p>gulp.watch() 用来监视文件的变化，当文件发生变化后，我们可以利用它来执行相应的任务，例如文件压缩等。其语法为：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gulp.<span class="title function_">watch</span>(glob[, opts], tasks);</span><br></pre></td></tr></table></figure><p><strong>glob</strong> 为要监视的文件匹配模式，规则和用法与 gulp.src() 方法中的 glob 相同。<br><strong>opts</strong> 为一个可选的配置对象，通常不需要用到。<br><strong>tasks</strong> 为文件变化后要执行的任务，为一个数组</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">gulp.<span class="title function_">task</span>(<span class="string">&quot;uglify&quot;</span>, <span class="keyword">function</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="comment">//do something</span></span><br><span class="line">&#125;);</span><br><span class="line">gulp.<span class="title function_">task</span>(<span class="string">&quot;reload&quot;</span>, <span class="keyword">function</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="comment">//do something</span></span><br><span class="line">&#125;);</span><br><span class="line">gulp.<span class="title function_">watch</span>(<span class="string">&quot;js/**/*.js&quot;</span>, [<span class="string">&quot;uglify&quot;</span>,<span class="string">&quot;reload&quot;</span>]);</span><br></pre></td></tr></table></figure><p>gulp.watch(glob [,opts, cb])<br><strong>glob</strong> 和 <strong>opts</strong> 参数与第一种用法相同<br><strong>cb</strong> 参数为一个函数。每当监视的文件发生变化时，就会调用这个函数，并且会给它传入一个对象，该对象包含了文件变化的一些信息，type 属性为变化的类型，可以是 added 、changed 、deleted ，path 属性为发生变化的文件的路径</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">gulp.<span class="title function_">watch</span>(<span class="string">&quot;js/**/*.js&quot;</span>, <span class="keyword">function</span>(<span class="params">event</span>)&#123;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(event.<span class="property">type</span>); <span class="comment">//变化类型added为新增，deleted为删除，changed为改变</span></span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(event.<span class="property">path</span>); <span class="comment">//变化的文件的路径</span></span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><h1 id="gulp-的插件"><a href="#gulp-的插件" class="headerlink" title="gulp 的插件"></a>gulp 的插件</h1><p>gulp 本身虽然不能完成很多任务，但它有大量插件可用，我们可以在 <a target="_blank" rel="noopener" href="http://gulpjs.com/plugins/">插件页面</a> 或者在 npm 搜索 gulpplugin 。<br>列一些很棒的 plugin ：</p><ul><li><a target="_blank" rel="noopener" href="https://www.npmjs.com/package/gulp-jshint/">JSHint</a> ： js代码检查分析工具</li><li><a target="_blank" rel="noopener" href="https://www.npmjs.com/package/gulp-coffee/">gulp-coffee</a> ： 编译CoffeeScript</li><li><a target="_blank" rel="noopener" href="https://www.npmjs.com/package/gulp-mocha">gulp-mocha</a> ： 执行Mocha测试</li><li><a target="_blank" rel="noopener" href="https://www.npmjs.com/package/gulp-bump">gulp-bump</a> ： 更新版本号</li><li><a target="_blank" rel="noopener" href="https://www.npmjs.com/package/gulp-sass">gulp-sass</a> ： sass 编译</li><li><a target="_blank" rel="noopener" href="http://www.browsersync.cn/docs/gulp/">browser-sync</a> ： 浏览器自动刷新</li><li><a target="_blank" rel="noopener" href="https://www.npmjs.com/package/gulp-uglify">gulp-uglify</a> ： 代码压缩</li><li><a target="_blank" rel="noopener" href="https://www.npmjs.com/package/gulp-concat">gulp-concat</a> ： 合并</li><li><a target="_blank" rel="noopener" href="https://www.npmjs.com/package/gulp-eslint">gulp-eslint</a> ： 支持 ES6 JSX</li></ul><h1 id="gulp-命令行参数"><a href="#gulp-命令行参数" class="headerlink" title="gulp 命令行参数"></a>gulp 命令行参数</h1><ul><li><code>-v</code> 或 <code>--version</code> 会显示全局和项目本地所安装的 gulp 版本号</li><li><code>--require &lt;module path&gt;</code> 将会在执行之前 require 一个模块。这对于一些语言编译器或者需要其他应用的情况来说很有用。你可以使用多个 <code>--require</code></li><li><code>--gulpfile &lt;gulpfile path&gt;</code> 手动指定一个 gulpfile 的路径，这在你有很多个 gulpfile 的时候很有用。这也会将 CWD 设置到该 gulpfile 所在目录</li><li><code>--cwd &lt;dir path&gt;</code> 手动指定 CWD 。定义 gulpfile 查找的位置，此外，所有的相应的依赖（require）会从这里开始计算相对路径</li><li><code>-T</code> 或 <code>--tasks</code> 会显示所指定 gulpfile 的 task 依赖树</li><li><code>--tasks-simple</code> 会以纯文本的方式显示所载入的 gulpfile 中的 task 列表</li><li><code>--color</code> 强制 gulp 和 gulp 插件显示颜色，即便没有颜色支持</li><li><code>--no-color</code> 强制不显示颜色，即便检测到有颜色支持</li><li><code>--silent</code> 禁止所有的 gulp 日志</li></ul><p>命令行会在 process.env.INIT_CW 中记录它是从哪里被运行的。</p><h1 id="tip"><a href="#tip" class="headerlink" title="tip"></a>tip</h1><p>1、gulp 写进项目 package.json 文件的依赖有什么作用<br>方便别人查看你项目中有些什么依赖，而且在项目目录下执行 npm install 命令会安装项目 package.json 中的所有依赖模块，这样就能简化项目的安装程序了，不用一个一个模块去安装啊。</p><p>2、gulp 中着重了解 gulp.task() 如何处理依赖任务是耗时操作或者异步操作的情况。</p></article><div class="post-copyright"><div class="post-copyright__author_group"><a class="post-copyright__author_img" href="/about/"><img class="post-copyright__author_img_front" src="/static/img/avatar.jpeg"></a><div class="post-copyright__author_name">Alcex</div><div class="post-copyright__author_desc">你所热爱的，就是你的生活</div></div><div class="post-tools" id="post-tools"><div class="post-tools-left"><div id="quit-box" onclick="RemoveRewardMask()"></div><div class="post-reward"><div class="reward-button" title="赞赏作者" onclick="AddRewardMask()"><i class="solitude st-hand-heart-fill"></i>赞赏作者</div><div class="reward-main"><ul class="reward-all"><span class="reward-title">感谢您的赞赏。</span><ul class="reward-group"><li class="reward-item"><a href="/"><img class="post-qr-code-img nolazyload" src="/static/img/alipay.png" alt="支付宝" style="border-color:var(--efu-black)"></a><div class="post-qr-code-desc">支付宝</div></li></ul><a class="reward-main-btn" href="/about"><div class="reward-text">赞赏名单</div><div class="reward-dec">因为有你们的支持，我才体会到写文章的价值。</div></a></ul></div></div><script>function RemoveRewardMask(){let e=document.querySelectorAll(".reward-main"),l=document.querySelector("#quit-box");e.forEach((e=>{e.style.display="none"})),l&&(l.style.display="none")}function AddRewardMask(){let e=document.querySelectorAll(".reward-main"),l=document.querySelector("#quit-box");e.forEach((e=>{e.style.display="flex"})),l&&(l.style.display="flex")}</script><div class="reward-link mode"><a class="reward-link-button" href="/atom.xml"><i class="solitude st-plant-fill"></i>订阅</a></div></div></div><div class="post-copyright__notice"><span class="post-copyright-info">本文是原创文章，采用<a target="_blank" rel="noopener" href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh">CC BY-NC-SA 4.0</a>协议，完整转载请注明来自<a href="/">Alcex</a></span></div></div><div class="post-tools-right"><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/gulp/"><span class="tags-punctuation"></span>gulp<span class="tagsPageCount">1</span></a></div></div><div class="social-share"><a class="social-share-ico icon-qq" target="_blank" rel="noopener" href="https://connect.qq.com/widget/shareqq/index.html?url=https%3A%2F%2Fblog.alcex.cn%2Fposts%2F486480be%2F&amp;title=gulp%20%E8%AF%A6%E8%A7%A3%E4%B8%8E%E4%BD%BF%E7%94%A8&amp;desc=undefined&amp;summary=undefined&amp;site=gulp%20%E8%AF%A6%E8%A7%A3%E4%B8%8E%E4%BD%BF%E7%94%A8&amp;pics=https%3A%2F%2Fbu.dusays.com%2F2024%2F05%2F05%2F66365fd49d7f5.jpg" title="QQ"></a><a class="social-share-ico icon-weibo" target="_blank" rel="noopener" href="http://service.weibo.com/share/share.php?url=https%3A%2F%2Fblog.alcex.cn%2Fposts%2F486480be%2F&amp;title=gulp%20%E8%AF%A6%E8%A7%A3%E4%B8%8E%E4%BD%BF%E7%94%A8&amp;pic=https%3A%2F%2Fbu.dusays.com%2F2024%2F05%2F05%2F66365fd49d7f5.jpg" title="Weibo"></a><a class="social-share-ico icon-telegram" target="_blank" rel="noopener" href="https://t.me/share/url?url=https%3A%2F%2Fblog.alcex.cn%2Fposts%2F486480be%2F&amp;text=gulp%20%E8%AF%A6%E8%A7%A3%E4%B8%8E%E4%BD%BF%E7%94%A8" title="Telegram"></a><a class="social-share-ico icon-linkedin" target="_blank" rel="noopener" href="https://www.linkedin.com/shareArticle?mini=true&amp;url=https%3A%2F%2Fblog.alcex.cn%2Fposts%2F486480be%2F&amp;title=gulp%20%E8%AF%A6%E8%A7%A3%E4%B8%8E%E4%BD%BF%E7%94%A8&amp;summary=undefined&amp;source=gulp%20%E8%AF%A6%E8%A7%A3%E4%B8%8E%E4%BD%BF%E7%94%A8" title="LinkedIn"></a></div></div><nav class="needEndHide pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/posts/20240504a/"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">零成本为网站增加 ipv6 支持</div></div></a></div><div class="next-post pull-right"><a href="/posts/2023429a1/"><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">使用 Github Action 自动化部署 hexo</div></div></a></div></nav><div id="post-comment"><div class="comment-head"><div class="comment-headline"><i class="solitude st-chat-fill"></i> <span>评论</span> <span class="count">(<span class="twikoo-count"><i class="solitude st-loading-line"></i></span>)</span></div></div><div class="comment-wrap"><div id="twikoo-wrap"></div></div></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="card-content"><div class="card-info-avatar is-center"><div class="author-info__top-group"><div class="author-info__sayhi" id="author-info__sayhi" onclick="sco.changeSayHelloText()">sayhello.morning</div></div></div><div class="avatar-img-group"><img class="avatar-img" alt="头像" src="/static/img/avatar.jpeg"><div class="avatar-sticker"><img class="avatar-sticker-img" src="https://7.isyangs.cn/34/65f2e4e0423cc-34.png" alt="心情贴纸"></div></div><div class="author-info__description_group"><div class="author-info__description">分享自己对编程的<b>热爱</b>，对美好生活的<b>向往</b>，对知识海洋<b>探索历程</b>。</div><div class="author-info__description2">相信你可以在这里找到对你有用的知识和教程。</div></div><div class="author-info__bottom-group"><a class="author-info__bottom-group-left" href="/about/"><div class="author-info__name">Alcex</div><div class="author-info__desc">你所热爱的，就是你的生活</div></a><div class="card-info-social-icons is-center"><a class="social-icon" target="_blank" rel="noopener" href="https://github.com/Alcexn" title="Github"><i class="solitude st-github-line"></i></a><a class="social-icon" target="_blank" rel="noopener" href="https://b23.tv/sJfQSqt" title="Bilibili"><i class="solitude st-bilibili-line"></i></a></div></div></div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="solitude st-menu-line"></i><span>文章目录</span></div><div class="toc-content" id="toc-content"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#%E4%BB%80%E4%B9%88%E6%98%AF-gulp"><span class="toc-text">什么是 gulp</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E7%94%A8-gulp"><span class="toc-text">为什么要用 gulp</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8-gulp"><span class="toc-text">如何使用 gulp</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#Installing-Gulp"><span class="toc-text">Installing Gulp</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#Install-the-gulp-command"><span class="toc-text">Install the gulp command</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Install-gulp-in-your-devDependencies"><span class="toc-text">Install gulp in your devDependencies</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Create-a-gulpfile"><span class="toc-text">Create a gulpfile</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Test-it-out"><span class="toc-text">Test it out</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#gulp-API"><span class="toc-text">gulp API</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#gulp-src"><span class="toc-text">gulp.src()</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#gulp-dest"><span class="toc-text">gulp.dest()</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#gulp-task"><span class="toc-text">gulp.task()</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#gulp-watch"><span class="toc-text">gulp.watch()</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#gulp-%E7%9A%84%E6%8F%92%E4%BB%B6"><span class="toc-text">gulp 的插件</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#gulp-%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%8F%82%E6%95%B0"><span class="toc-text">gulp 命令行参数</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#tip"><span class="toc-text">tip</span></a></li></ol></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="solitude st-map-line"></i><span>最近发布</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/posts/20240504a/" title="零成本为网站增加 ipv6 支持"><img alt="零成本为网站增加 ipv6 支持" src="https://bu.dusays.com/2024/05/04/6636573f6067e.jpeg"></a><div class="content"><a class="title" href="/posts/20240504a/" title="零成本为网站增加 ipv6 支持">零成本为网站增加 ipv6 支持</a><a class="article-recent_post_categories" href="/posts/20240504a/">Cloudflare</a></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/486480be/" title="gulp 详解与使用"><img alt="gulp 详解与使用" src="https://bu.dusays.com/2024/05/05/66365fd49d7f5.jpg"></a><div class="content"><a class="title" href="/posts/486480be/" title="gulp 详解与使用">gulp 详解与使用</a><a class="article-recent_post_categories" href="/posts/486480be/">前端</a></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/2023429a1/" title="使用 Github Action 自动化部署 hexo"><img alt="使用 Github Action 自动化部署 hexo" src="https://bu.dusays.com/2023/10/01/65198524c5968.png"></a><div class="content"><a class="title" href="/posts/2023429a1/" title="使用 Github Action 自动化部署 hexo">使用 Github Action 自动化部署 hexo</a><a class="article-recent_post_categories" href="/posts/2023429a1/">hexo</a></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/16107/" title="Hello World"><img alt="Hello World" src="/static/img/scaffolds.webp"></a><div class="content"><a class="title" href="/posts/16107/" title="Hello World">Hello World</a></div></div></div></div></div></div></main><footer id="footer"><div id="st-footer-bar"><div class="footer-logo"><span>Alcex</span></div><div class="footer-bar-description">来自Alcex - 你所热爱的，就是你的生活的文章</div><a class="footer-bar-link" href="/">了解更多</a></div><div id="footer_deal"><a class="deal_link" target="_blank" rel="noopener" href="https://github.com/alcexn" title="Github"><i class="solitude st-github-line"></i></a><a class="deal_link" href="/admin@alcex.cn" title="Mail"><i class="solitude st-mail-line"></i></a><div class="nolazyload footer_mini_logo" id="footer_mini_logo" title="返回顶部" onclick="sco.toTop()"><img src="/static/img/svg/loading.svg" data-lazy-src="/static/img/avatar.jpeg" alt="返回顶部"></div><a class="deal_link" target="_blank" rel="noopener" href="https://space.bilibili.com/1329819902" title="Bilibili"><i class="solitude st-bilibili-line"></i></a><a class="deal_link" target="_blank" rel="noopener" href="https://v.douyin.com/iY2P2d92/" title="Douyin"><i class="solitude st-douyin-fill"></i></a></div><div id="st-footer"><div class="footer-group"><h3 class="footer-title">导航</h3><div class="footer-links"><a class="footer-item" href="/archives/" title="归档">归档</a><a class="footer-item" href="/categories/" title="分类">分类</a><a class="footer-item" href="/tags/" title="标签">标签</a></div></div><div class="footer-group"><h3 class="footer-title">服务</h3><div class="footer-links"><a class="footer-item" target="_blank" rel="noopener" href="https://aliyun.com/" title="阿里云">阿里云</a><a class="footer-item" target="_blank" rel="noopener" href="https://v6.51.la/" title="51la统计">51la统计</a><a class="footer-item" target="_blank" rel="noopener" href="https://tongji.baidu.com/" title="百度统计">百度统计</a></div></div><div class="footer-group"><h3 class="footer-title">支持</h3><div class="footer-links"><a class="footer-item" href="/about/" title="打赏记录">打赏记录</a></div></div><div class="footer-group"><h3 class="footer-title">协议</h3><div class="footer-links"><a class="footer-item" href="/cookies/" title="Cookies">Cookies</a><a class="footer-item" href="/privacy/" title="用户协议">用户协议</a><a class="footer-item" href="/copyright/" title="版权协议">版权协议</a></div></div><div class="footer-group"><div class="footer-title-group"><h3 class="footer-title">友链</h3><button class="random-friends-btn" onclick="randomLinksList()" title="友链"><i class="solitude st-refresh-line"></i></button></div><div class="footer-links" id="friend-links-in-footer"></div></div></div><div id="footer-bar"><div class="footer-bar-links"><div class="footer-bar-left"><div class="copyright">© 2023 - 2024 By&nbsp;<a class="footer-bar-link" href="/">Alcex</a></div></div><div class="footer-bar-right"><a class="footer-bar-link" target="_blank" rel="noopener" href="https://github.com/valor-x/hexo-theme-solitude" title="主题">主题</a><a class="footer-bar-link" href="/atom.xml" alt="订阅">订阅</a><a class="footer-bar-link" target="_blank" rel="noopener" href="https://akilight.lightxi.com" alt="本站由晞云提供加速服务">本站由晞云提供加速服务</a><a class="footer-bar-link cc" href="/null" aria-label="copyright"><i class="solitude st-copyright-line"></i><i class="solitude st-creative-commons-by-line"></i><i class="solitude st-creative-commons-nc-line"></i><i class="solitude st-creative-commons-nd-line"></i></a></div></div></div><div class="needEndHide" id="cookies-window"><div class="cookies-window-title">协议提醒助手</div><div class="cookies-window-content"><span class="cookies-tip">查看本站为你的个人隐私做出的努力</span><a class="cookies-link" href="/privacy/" title="本站如何保护你的隐私"><i class="solitude st-right-btn-fill"></i></a></div></div><div class="comment-barrage needEndHide"></div></footer></div><div id="rightMenu"><div class="rightMenu-group rightMenu-small"><div class="rightMenu-item" id="menu-backward"><i class="solitude st-arrow-left-line"></i></div><div class="rightMenu-item" id="menu-forward"><i class="solitude st-arrow-right-line"></i></div><div class="rightMenu-item" id="menu-refresh"><i class="solitude st-restart-line"></i></div><div class="rightMenu-item" id="menu-top"><i class="solitude st-arrow-up-line"></i></div></div><div class="rightMenu-group rightMenu-line rightMenuPlugin"><div class="rightMenu-item" id="menu-copytext"><i class="solitude st-copy-fill"></i><span>复制选中文本</span></div><div class="rightMenu-item" id="menu-pastetext"><i class="solitude st-clipboard-fill"></i><span>粘贴文本</span></div><div class="rightMenu-item" id="menu-commenttext"><i class="solitude st-chat-new-fill"></i><span>引用到评论</span></div><div class="rightMenu-item" id="menu-newwindow"><i class="solitude st-window-fill"></i><span>新窗口打开</span></div><div class="rightMenu-item" id="menu-copylink"><i class="solitude st-link-line"></i><span>复制链接地址</span></div><div class="rightMenu-item" id="menu-copyimg"><i class="solitude st-copy-fill"></i><span>复制此图片</span></div><div class="rightMenu-item" id="menu-downloadimg"><i class="solitude st-download-cloud-fill"></i><span>下载此图片</span></div><div class="rightMenu-item" id="menu-search"><i class="solitude st-search-line"></i><span>站内搜索</span></div><div class="rightMenu-item" id="menu-music-toggle"><i class="solitude st-play-fill"></i><span>播放音乐</span></div><div class="rightMenu-item" id="menu-music-back"><i class="solitude st-skip-back-fill"></i><span>切换到上一首</span></div><div class="rightMenu-item" id="menu-music-forward"><i class="solitude st-skip-forward-fill"></i><span>切换到下一首</span></div><div class="rightMenu-item" id="menu-music-copyMusicName"><i class="solitude st-copy-fill"></i><span>复制歌名</span></div></div><div class="rightMenu-group rightMenu-line rightMenuOther"><div class="rightMenu-item" id="menu-randomPost" onclick="toRandomPost()||rm.hideRightMenu()"><i class="solitude st-signal-tower-fill"></i><span>随机短文</span></div><div class="rightMenu-item" onclick='pjax.loadUrl("/categories/")||rm.hideRightMenu()'><i class="solitude st-checkbox-multiple-blank-fill"></i><span>全部分类</span></div><div class="rightMenu-item" onclick='pjax.loadUrl("/tags/")||rm.hideRightMenu()'><i class="solitude st-price-tag-fill"></i><span>全部标签</span></div></div><div class="rightMenu-group rightMenu-line rightMenuOther"><div class="rightMenu-item" id="menu-commentBarrage" onclick="sco.switchCommentBarrage()"><i class="solitude st-chat-fill"></i><span class="menu-commentBarrage-text">关闭热评</span></div><div class="rightMenu-item" id="menu-darkmode" onclick="sco.switchDarkMode()"><i class="solitude st-moon-clear-fill"></i><span class="menu-darkmode-text">深色模式</span></div><div class="rightMenu-item" id="menu-translate"><i class="solitude st-panben-line"></i><span>轉為繁體</span></div></div></div><div id="rightmenu-mask"></div><div><script src="/js/utils.js?v=1.9.2"></script><script src="/js/main.js?v=1.9.2"></script><script src="/js/third_party/waterfall.min.js?v=1.9.2"></script><script src="https://cdn.staticfile.net/pjax/0.2.8/pjax.min.js"></script><script src="/js/third_party/universe.min.js?v=1.9.2"></script><script>dark()</script><script src="/js/tw_cn.js?v=1.9.2"></script><script src="https://cdn.staticfile.net/vanilla-lazyload/19.1.3/lazyload.iife.min.js"></script><script src="https://cdn.staticfile.net/node-snackbar/0.1.16/snackbar.min.js"></script><script src="https://cdn.staticfile.net/fancyapps-ui/5.0.36/fancybox/fancybox.umd.min.js"></script><script src="https://cdn.staticfile.net/Swiper/11.0.5/swiper-bundle.min.js"></script><script src="/js/third_party/efu_ai.min.js?v=1.9.2"></script><script>var meting_api="https://meting.qjqq.cn/?server=:server&type=:type&id=:id&auth=:auth&r=:r"</script><script src="https://cdn.staticfile.net/aplayer/1.10.1/APlayer.min.js"></script><script src="https://cdn.staticfile.net/meting/2.0.1/Meting.min.js"></script><script>const coverColorConfig={api:"https://api.qjqq.cn/api/Imgcolor?img=",time:432e5}</script><script src="/js/covercolor/api.js?v=1.9.2"></script><script src="https://cdn.staticfile.net/pace/1.2.4/pace.min.js"></script><script src="https://cdn.staticfile.net/instantsearch.js/4.66.1/instantsearch.production.min.js"></script><script src="https://cdn.staticfile.net/algoliasearch/4.23.2/algoliasearch-lite.umd.min.js"></script><script src="/js/right_menu.js?v=1.9.2"></script><script defer pjax src="/static/js/custom.js"></script><div class="js-pjax"><script>(()=>{const o=()=>{twikoo.init(Object.assign({el:"#twikoo-wrap",envId:"https://twikoo.alcex.cn/",region:"",path:window.location.pathname,onCommentLoaded:()=>{GLOBAL_CONFIG.lightbox&&utils.lightbox(document.querySelectorAll("#twikoo .tk-content img:not(.tk-owo-emotion)"))}},null))&&(()=>{const o=document.querySelectorAll(".twikoo-count");o&&twikoo.getCommentsCount({envId:"https://twikoo.alcex.cn/",region:"",urls:[window.location.pathname],includeReply:!1}).then((t=>{o.forEach((o=>o.textContent=t[0].count))})).catch((o=>{console.error(o)}))})(),sco.owoBig({body:".OwO-body",item:".OwO-items li"}),barrageTwikoo()},t=()=>{"object"==typeof twikoo?setTimeout(o,0):utils.getScript("https://cdn.staticfile.net/twikoo/1.6.32/twikoo.all.min.js").then(o)};utils.loadComment(document.getElementById("twikoo-wrap"),t)})()</script><script>async function barrageTwikoo(){await fetch("https://twikoo.alcex.cn/",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({event:"COMMENT_GET",accessToken:"d785c99d298a4e9e6e13fe99e602ef42",url:window.location.pathname})}).then((async e=>{if(!e.ok)throw new Error("HTTP error! status: "+e.status);const t=await e.json(),n=()=>{initializeCommentBarrage(t.data.map((e=>Object.assign({content:e.comment,nick:e.nick,mailMd5:e.mailMd5,id:e.id}))))};"undefined"==typeof initializeCommentBarrage?await utils.getScript("/js/barrage_comment.js?v=1.9.2").then(n):n()})).catch((e=>console.error("An error occurred while fetching comments: ",e)))}</script><script defer pjax src="https://cdn.staticfile.net/busuanzi/2.3.0/bsz.pure.mini.min.js"></script></div></div><script>const links=[{name:"杜老师说",link:"https://dusays.com"},{name:"Ganzhe",link:"https://ganzhe2028.github.io"},{name:"Yuzifu's Blog",link:"https://blog.yzf.moe/"},{name:"网笙久久",link:"https://www.wsjj.top"},{name:"云晓晨CatchYun",link:"https://blog.catchyun.com/"},{name:"Ganzhe",link:"https://ganzhe2028.github.io"},{name:"lukelzlz",link:"https://lukelzlz.top/"},{name:"星穹CDN",link:"https://www.domecdn.com/"},{name:"StarDreamNet",link:"https://cloudroo.top"}],randomText="您即将前往 ⌈ ${name} ⌋ , 安全性未知";function travelling(){const n=links[utils.randomNum(links.length)];utils.snackbarShow(randomText.replace(/\$\{name}/,n.name),!1,3e3),setTimeout((()=>{window.open(n.link,"_blank")}),3e3)}</script><script>function randomLinksList(){const e=document.getElementById("friend-links-in-footer");if(null==e)return;let n="",t=[...links],l=Math.min(3,t.length);for(let e=0;e<l;e++){let e=utils.randomNum(t.length);const{link:l,name:o}=t[e];n+=`<a class="footer-item" href="${l}" target="_blank" rel="noopener noreferrer nofollow">${o}</a>`,t.splice(e,1)}e.innerHTML=n+'<a class="footer-item" href="/links/">更多</a>'}</script><script>window.addEventListener("load",(()=>{const e=e=>{if(!e)return"";return(e=[{regex:/<img.*?src="(.*?)"?[^\>]+>/gi,replacement:"[图片]"},{regex:/<a[^>]+?href=["']?([^"']+)["']?[^>]*>([^<]+)<\/a>/gi,replacement:"[链接]"},{regex:/<pre><code>.*?<\/pre>/gi,replacement:"[代码]"},{regex:/<[^>]+>/g,replacement:""}].reduce(((e,{regex:t,replacement:n})=>e.replace(t,n)),e)).length>150?`${e.substring(0,150)}...`:e},t=e=>{const t=e.map((e=>`\n            <div class='aside-list-item'>\n                <a onclick='pjax.loadUrl("${e.url}")' class='thumbnail'>\n                    <img src= "/static/img/svg/loading.svg" data-lazy-src='${e.avatar}' alt='${e.nick}'>\n                    <div class='name'><span>${e.nick}</span></div>\n                </a>\n                <div class='content'>\n                    <a class='comment' onclick='pjax.loadUrl("${e.url}")'>${e.content}</a>\n                    <time class="datetime" datetime="${e.date}"></time>\n                </div>\n            </div>\n        `)).join("");document.querySelector("#card-newest-comments .aside-list").innerHTML=e.length?t:"没有评论",window.lazyLoadInstance?.update(),window.pjax?.refresh(),sco?.changeTimeFormat(document.querySelectorAll(".aside-list-item time"))};(()=>{const n=utils.saveToLocal.get("twikoo-newest-comment");n?t(n):(async()=>{const n=()=>{twikoo.getRecentComments({envId:"https://twikoo.alcex.cn/",region:"",pageSize:6,includeReply:!0}).then((n=>{const a=n.map((t=>({content:e(t.comment),avatar:t.avatar,nick:t.nick,url:`${t.url}#${t.id}`,date:new Date(t.created).toString()})));utils.saveToLocal.set("twikoo-newest-comment",a,.5),t(a)})).catch((e=>{console.error(e),document.querySelector("#card-newest-comments .aside-list").textContent="无法获取评论，请确认相关配置是否正确。"}))};"object"==typeof twikoo?n():utils.getScript("https://cdn.staticfile.net/twikoo/1.6.32/twikoo.all.min.js").then(n)})()})()}))</script><script>const pjax=new Pjax({elements:'a:not([target="_blank"])',selectors:["title","#body-wrap","#site-config",'meta[name="description"]',".js-pjax",'meta[property^="og:"]',"#config-diff"],cacheBust:!1,analytics:!1,scrollRestoration:!1});document.querySelectorAll("script[data-pjax]").forEach((e=>{const t=document.createElement("script"),a=e.text||e.textContent||e.innerHTML||"";Array.from(e.attributes).forEach((e=>t.setAttribute(e.name,e.value))),t.appendChild(document.createTextNode(a)),e.parentNode.replaceChild(t,e)})),document.addEventListener("pjax:complete",(()=>{window.refreshFn(),document.querySelectorAll("script[data-pjax]").forEach((e=>{const t=document.createElement("script"),a=e.text||e.textContent||e.innerHTML||"";Array.from(e.attributes).forEach((e=>t.setAttribute(e.name,e.value))),t.appendChild(document.createTextNode(a)),e.parentNode.replaceChild(t,e)})),GLOBAL_CONFIG.islazyload&&window.lazyLoadInstance.update()})),document.addEventListener("pjax:error",(e=>{404===e.request.status&&pjax.loadUrl("/404.html")}))</script><script>initTheme=()=>{let e=window.matchMedia("(prefers-color-scheme: dark)").matches;const t=utils.saveToLocal.get("theme");if(void 0===t){const t=e?"dark":"light";document.documentElement.setAttribute("data-theme",t)}else document.documentElement.setAttribute("data-theme",t);is_rm&&rm.mode("dark"===t&&e)},initTheme()</script><div id="algolia-search"><div class="search-dialog"><div class="algolia-navbar"><div class="search-dialog__title" id="algolia-search-title">搜索</div><div class="algolia-tips"><i class="solitude st-algolia-fill"></i><span class="algolia-tips-text">Algolia</span></div><span class="search-close-button"><i class="solitude st-close-fill"></i></span></div><div id="algolia-input-panel"><div id="algolia-search-input"></div></div><div id="search-results"><div id="algolia-hits"></div></div><div id="algolia-tips"><div id="algolia-pagination"></div><div id="algolia-stats"></div></div></div><div id="search-mask"></div></div><script src="/js/search/algolia.js?v=1.9.2"></script><div class="needEndHide" id="nav-music" onclick="sco.musicToggle()"><div id="nav-music-hoverTips">音乐已暂停</div><meting-js id="5361218008" server="netease" type="playlist" mutex="true" preload="none" data-lrctype="0" order="random" theme="var(--efu-main)"></meting-js></div></body></html><script>const posts=["posts/486480be/","posts/16107/","posts/20240504a/","posts/2023429a1/"];function toRandomPost(){pjax.loadUrl("/"+posts[Math.floor(Math.random()*posts.length)])}</script>